<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>

    /* es6 的类的写法
        1. 对象属性
        2. 对象方法
        */
    class Person {

        /* 可以把私有的书写直接写在constructor外部 */
        _salary = 2000;


        constructor(name, age) {
            this.username = name;
            this.age = age;
            /* 因为我们的javascript里面没有私有属性一说。在纯面向对象的语言里面
                属性和方法修饰符有
                    1. public 代表属性和方法是公开的，到处都可以使用
                    2. protected 代表属性和方法是受保护的，只能在当前类及其子类的内部使用
                    3. private 代表是私有的，只能在本类的内部使用

                但是我们的javascript是不执行属性修饰符的。所有我们习惯使用 _ 开头的属性作为私有属性（约定俗成）

                https://es6.ruanyifeng.com/#docs/class#%E7%A7%81%E6%9C%89%E6%96%B9%E6%B3%95%E5%92%8C%E7%A7%81%E6%9C%89%E5%B1%9E%E6%80%A7


                https://es6.ruanyifeng.com/#docs/class#%E7%A7%81%E6%9C%89%E5%B1%9E%E6%80%A7%E7%9A%84%E6%8F%90%E6%A1%88

            */
            // this._salary = 2000;

        }

        /* 通过私有属性的get和set可以达到对属性的控制（限定作业） */
        /* 定义一个专门的方法去操作（1.读取 2. 设置） */
        /* set 和 get 属于程序猿的一个业界约束俗成的写法。在es6里面做到规范，官方提供 get 和 set 的写法 */
        /* 只需要在方法的前面加上 get 和 set 关键字去定义好方法即可 */

        /* 注意：
            1. 定义的时候，是一个方法，但是调用的时候，是一个属性
            2. 在定义的方法里面是不能写 this.salary = salary 的，因为这样的话，会把salary的值赋给了salary属性

            https://es6.ruanyifeng.com/#docs/class#%E5%AE%9E%E4%BE%8B%E5%B1%9E%E6%80%A7%E7%9A%84%E6%96%B0%E5%86%99%E6%B3%95
            
        */
        get salary() {
            /* Maximum call stack size exceeded */
            // return this.salary; //这样是不可以的，是死循环

            /* 自己在私有化一个属性 */
            return this._salary;
        }

        set salary(salary) {
            console.log('set')
            /* 可以限定一下 salary 范围 */
            if (salary <= 5000) {
                this._salary = salary;
            } else {
                throw new Error("slary is too high");
            }
        }
    }

    let p = new Person('zhangsan', 20);

    //  get salary() {} 方法的定义，但是以属性的方式调用
    console.log('设置前：', p.salary);

    /* 原先的get和set直接以属性方式调用 */
    // p.setSalay(3000);
    // p.setSalay(30000);
    p.salary = 3500;

    console.log('设置后：', p.salary);



</script>

</html>